import type { App } from 'vue'
import cordova from '@/js/cordova'
import { fxEventBus } from '@/js/eventBus'
import { useWeight } from '@/js/hooks'
import { fxEventBusKey } from '@/config/app_eventbus_config'
import vuex from '@/store'
import windUi from '@/components/wind-ui'

const { connected, isIntegratedScale, isUsbScale } = useWeight()
export interface WeightState {
	isStable: boolean
	weight: number
	isTared: boolean
	isZero: boolean
	peelMode: string
	peelData: number
}
interface BatteryState {
	isCharge: boolean
	voltage: number
	'voltage_percent'?: string
	voltagePercent: string
}


class FxWeigh {
	public scaleType = 0
	public scaleName = ''
	scan () {
		if (this.isIntegratedScale() || this.isUsbScale()) {
			return Promise.resolve({
				address: '',
				name: this.scaleName,
				deviceType: 1
			})
		}
		return cordova.scanBluetooth.scan()
	}

	connect (address: string, name: string, silent?: boolean) {
		let connectFn = cordova.scale.connectBluetoothScale
		if (this.isIntegratedScale()) {
			connectFn = cordova.scale.connectIntegratedScale
		} else if (this.isUsbScale()) {
			connectFn = cordova.scale.connectUsbScale
		}
		return connectFn(address, name, silent).then((result) => {
			vuex.commit('SET_SYSTEM', {
				deviceScaleName: name,
				deviceScaleAddress: address
			})
			connected.value = true
			return Promise.resolve(result)
		})
	}

	emitState () {
		return cordova.scale.onStateChange((state: object) => {
			fxEventBus.emit(fxEventBusKey.WEIGHT_STATE_CHANGE, state)
		})
	}

	onListenerState (fn: (state: WeightState) => void) {
		fxEventBus.on(fxEventBusKey.WEIGHT_STATE_CHANGE, (state: WeightState) => {
			const weighState: WeightState = {
				weight: Number(state.weight),
				isStable: state.isStable,
				isTared: state.isTared,
				isZero: state.isZero,
				peelMode: state.peelMode,
				peelData: Number(state.peelData)
			}
			fn(weighState)
		})
	}

	offListenerState (fn: Function) {
		fxEventBus.off(fxEventBusKey.WEIGHT_STATE_CHANGE, fn)
	}

	emitBatteryState () {
		return cordova.scale.onBatteryChange((state: object) => {
			fxEventBus.emit(fxEventBusKey.WEIGHT_BATTERY_CHANGE, state)
		})
	}

	onListenerBatteryState (fn: (state: BatteryState) => void) {
		fxEventBus.on(fxEventBusKey.WEIGHT_BATTERY_CHANGE, (state: BatteryState) => {
			const batteryState: BatteryState = {
				isCharge: state.isCharge,
				voltage: state.voltage,
				voltagePercent: state.voltage_percent!
			}
			fn(batteryState)
		})
	}

	offListenerBatteryState (fn: Function) {
		fxEventBus.off(fxEventBusKey.WEIGHT_BATTERY_CHANGE, fn)
	}

	setTare () {
		if (!connected.value) {
			return windUi.$fxMessage.warning('请连接电子秤!')
		}
		return cordova.scale.setTare()
	}

	setBoxTare (boxTare: number) {
		return cordova.scale.setBoxTare(boxTare)
	}

	setZero () {
		if (!connected.value) {
			return windUi.$fxMessage.warning('请连接电子秤!')
		}
		return cordova.scale.setZero()
	}

	getDeviceType () {
		return cordova.scale.getDeviceType()
	}

	isIntegratedScale (scaleType = this.scaleType) {
		return scaleType === 1
	}

	isUsbScale (scaleType = this.scaleType) {
		return scaleType === 3
	}

	isIntegratedOrUsbScale () {
		return this.isIntegratedScale() || this.isUsbScale()
	}

	initWeighDevice () {
		if (connected.value) {
			return Promise.resolve({
				scaleType: this.scaleType,
				scaleName: this.scaleName
			})
		}
		return this.getDeviceType().then(res => {
			this.scaleType = res.scaleType
			this.scaleName = res.scaleName
			if (this.isIntegratedScale()) {
				isIntegratedScale.value = true
				this.connectAndListenerWeigh()
			} else if (this.isUsbScale()) {
				isUsbScale.value = true
				this.connectAndListenerWeigh()
			} else {
				this.connectAndListenerWeighSilent()
			}
			return Promise.resolve(res)
		})
	}

	connectAndListenerWeigh () {
		return this.scan().then((device: { address: string, name: string }) => {
			return this.connect(device.address, device.name).then(() => {
				this.emitState()
				this.emitBatteryState()
				return Promise.resolve()
			})
		})
	}

	connectAndListenerWeighSilent () {
		const deviceScaleName = vuex.getters.getDeviceScaleName
		const deviceScaleAddress = vuex.getters.getDeviceScaleAddress
		if (connected.value || !deviceScaleName || !deviceScaleAddress) {
			return Promise.resolve()
		}
		return this.connect(deviceScaleAddress, deviceScaleName, true).then(() => {
			this.emitState()
			this.emitBatteryState()
			return Promise.resolve()
		})
	}

	setBluetoothDisConnectState () {
		connected.value = false
	}

	disConnectScale () {
		return cordova.scale.disConnectScale()
	}
}

export const fxWeigh = new FxWeigh()

const install = (app: App): void => {
	app.config.globalProperties.$fxWeigh = fxWeigh
}

export default {
	install,
	fxWeighInstance: fxWeigh
}
